<template>
  <div class="tuopu">
    <h2>使用三方库实现拓扑结构图</h2>
    <div id="container"></div>
    <div id="tooltipText" class="tooltiptext"></div>
  </div>
</template>

<script>
export default {
  name: "Tuopu",
};
</script>

<script setup>
import { Graph, Markup, Timing } from "@antv/x6";
import { onMounted } from "vue";

const init = () => {
  const imgl =
    "";
  // 创建画布
  const graph = new Graph({
    container: document.getElementById("container"),
    width: "100%",
    height: "100%",
    panning: true, //是否可以拖动
    mousewheel: true, //鼠标滚轮缩放
    interacting: false, // 定制行为，禁止拖动
    background: {
      color: "#000016",
    },
    onEdgeLabelRendered: (args) => {
      const { selectors } = args;
      const content =
        selectors.foContent instanceof HTMLDivElement
          ? selectors.foContent
          : null;
      if (content) {
        let data = args.label.data;
        let btn = null;
        btn = dataSet(data);
        content.appendChild(btn);
      }
    },
  });
  // 鼠标悬浮显示悬浮窗-节点
  graph.on("node:mouseenter", ({ node }) => {
    node.attr("body", {
      stroke: "orange",
      fill: "orange",
    });
    const text = document.querySelector("#tooltipText");
    const p1 = graph.localToGraph(
      node.store.data.position.x,
      node.store.data.position.y
    );
    text.innerHTML = node.store.changed.attrs.text.text;
    text.style.display = "block";
    text.style.left = (p1.x + 300).toString() + "px";
    text.style.top = (p1.y + 100).toString() + "px";
  });
  // 鼠标离开隐藏悬浮窗-节点
  graph.on("node:mouseleave", ({ node }) => {
    node.attr("body", {
      stroke: "rgb(255,255,0)",
      fill: "none",
    });
    const text = document.getElementById("tooltipText");
    text.style.display = "none";
  });
  // 鼠标悬浮变色-边
  let lineColor = "";
  graph.on("edge:mouseenter", ({ edge }) => {
    const id = edge.id;
    lineColor = edge.attrs.line.stroke;
    const edges = graph.getEdges();
    console.log(edges[edges.findIndex((item) => item.id === id)]);
    edges[edges.findIndex((item) => item.id === id)].attr(
      "line/stroke",
      "#fff"
    );
  });
  // 鼠标离开恢复-边
  graph.on("edge:mouseleave", ({ edge }) => {
    const id = edge.id;
    const edges = graph.getEdges();
    edges[edges.findIndex((item) => item.id === id)].attr(
      "line/stroke",
      lineColor
    );
  });
  // 点击事件
  graph.on("edge:click", ({ cell }) => {
    alert(
      "你点击的元素为：edge--antv/x6的边 \n如有后续操作可根据具体属性到代码中添加"
    );
  });
  graph.on("node:click", ({ cell }) => {
    alert(
      "你点击的元素为：node--antv/x6的节点 \n如有后续操作可根据具体属性到代码中添加"
    );
  });
  // 数据渲染
  const dataSet = (data) => {
    const btn = document.createElement("div");
    let span = document.createElement("div");
    data.name ? span.appendChild(document.createTextNode(data.name)) : "";
    btn.appendChild(span);
    let span0 = document.createElement("div");
    span0.appendChild(document.createTextNode("Na: " + data.U));
    data.U ? btn.appendChild(span0) : "";
    let span1 = document.createElement("div");
    span1.appendChild(document.createTextNode("Na: " + data.P));
    data.P ? btn.appendChild(span1) : "";
    let span2 = document.createElement("div");
    span2.appendChild(document.createTextNode("Na: " + data.Q));
    data.Q ? btn.appendChild(span2) : "";
    let span3 = document.createElement("div");
    span3.appendChild(document.createTextNode("Na: " + data.Pg));
    data.Pg ? btn.appendChild(span3) : "";
    let span4 = document.createElement("div");
    span4.appendChild(document.createTextNode("Na: " + data.Qg));
    data.Qg ? btn.appendChild(span4) : "";
    let span5 = document.createElement("div");
    span5.appendChild(document.createTextNode("模拟速率: " + data.Fz));
    data.Fz ? btn.appendChild(span5) : "";
    btn.style.width = "100%";
    btn.style.height = "90%";
    btn.style.fontWeight = "100";
    btn.style.fontSize = "12px";
    span.style.fontSize = "12px";
    span0.style.fontSize = "12px";
    span1.style.fontSize = "12px";
    span2.style.fontSize = "12px";
    span3.style.fontSize = "12px";
    span4.style.fontSize = "12px";
    span5.style.fontSize = "12px";
    span0.style.transform = "scale(.9)";
    span1.style.transform = "scale(.9)";
    span2.style.transform = "scale(.9)";
    span3.style.transform = "scale(.9)";
    span4.style.transform = "scale(.9)";
    span5.style.transform = "scale(.9)";
    span.style.color = "rgb(255,255,255)";
    span.style.marginTop = "5px";
    span.style.marginBottom = "5px";
    span.style.marginLeft = "2px";
    span5.style.color = "rgb(0,255,0)";
    btn.style.lineHeight = "1";
    btn.style.textAlign = "left";
    btn.style.color = "rgb(0,255,0)";
    btn.style.background = "transparent";
    btn.style.border = "0px solid transparent";
    btn.style.display = "flex";
    btn.style.flexDirection = "column";
    btn.style.justifyContent = "space-between";
    btn.style.alignItems = "flex-start";
    btn.style.boxSizing = "border-box";
    btn.style.cursor = "pointer";
    return btn;
  };
  // 两条母线
  graph.addEdge({
    source: { x: 40, y: 40 },
    target: { x: 1200, y: 40 },
    attrs: {
      line: {
        stroke: "rgb(255,0,0)",
        targetMarker: {},
      },
    },
  });
  graph.addEdge({
    source: { x: 40, y: 70 },
    target: { x: 1200, y: 70 },
    attrs: {
      line: {
        stroke: "rgb(255,0,0)",
        targetMarker: {},
      },
    },
  });
  // 两条母线引申线
  graph.addEdge({
    source: { x: 600, y: 40 },
    target: { x: 600, y: 188 },
    attrs: {
      line: {
        stroke: "rgb(255,0,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "",
      },
    },
    connector: {
      name: "jumpover",
      args: {
        type: "arc",
        size: 5,
        radius: 0,
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 70,
          x: 10,
          y: 0,
        },
      },
    },
    labels: [
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: -17.5,
            refY: 77,
            refWidth: 35,
            refHeight: 35,
            stroke: "rgb(255,0,0)",
            fill: "transparent",
            strokeWidth: 1,
            rx: 50,
            ry: 500,
          },
        },
        position: 0.5,
      },
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: -5,
            refY: -15,
            refWidth: 10,
            refHeight: 30,
            stroke: "rgb(255,0,0)",
            fill: "rgb(255,0,0)",
            strokeWidth: 0,
            rx: 0,
            ry: 0,
          },
        },
        position: 0.6,
      },
      {
        data: { U: "模拟数据", Fz: "0%" },
        position: 0.3,
      },
    ],
  });
  graph.addEdge({
    source: { x: 200, y: 70 },
    target: { x: 200, y: 190 },
    attrs: {
      line: {
        stroke: "rgb(255,0,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "",
      },
    },
    connector: {
      name: "jumpover",
      args: {
        type: "arc",
        size: 5,
        radius: 0,
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 70,
          x: 10,
          y: 0,
        },
      },
    },
    labels: [
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: -17.5,
            refY: 60,
            refWidth: 35,
            refHeight: 35,
            stroke: "rgb(255,0,0)",
            fill: "transparent",
            strokeWidth: 1,
            rx: 50,
            ry: 500,
          },
        },
        position: 0.5,
      },
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: -5,
            refY: -15,
            refWidth: 10,
            refHeight: 30,
            stroke: "rgb(255,0,0)",
            fill: "rgb(255,0,0)",
            strokeWidth: 0,
            rx: 0,
            ry: 0,
          },
        },
        position: 0.49,
      },
      {
        data: { U: "模拟数据", Fz: "0%" },
        position: 0.1,
      },
    ],
  });
  // 左侧支线1
  graph.addEdge({
    source: { x: 170, y: 225 },
    target: { x: 100, y: 300 },
    vertices: [{ x: 100, y: 225 }],
    attrs: {
      line: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 70,
          x: 0,
          y: -30,
        },
      },
    },
    labels: [
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: 70,
            refY: -17.5,
            refWidth: 35,
            refHeight: 35,
            stroke: "rgb(255,255,0)",
            fill: "transparent",
            strokeWidth: 1,
            rx: 50,
            ry: 500,
          },
        },
        position: 0.5,
      },
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: -5,
            refY: 20,
            refWidth: 10,
            refHeight: 30,
            stroke: "rgb(255,255,0)",
            fill: "#000016",
            strokeWidth: 1,
            rx: 0,
            ry: 0,
          },
        },
        position: 0.49,
      },
      {
        data: { name: "模拟数据", U: "模拟数据", Fz: "0%" },
        position: 0.2,
        attrs: {
          fo: {
            x: -120, // 设置x偏移
            y: -20, // 设置y偏移
          },
        },
      },
    ],
  });
  // 连接左侧的线路
  graph.addEdge({
    source: { x: 20, y: 300 },
    target: { x: 180, y: 300 },
    attrs: {
      line: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "",
      },
    },
  });
  // 两个节点
  const target1 = graph.addNode({
    x: 30,
    y: 350,
    width: 60,
    height: 20,
    label: "模拟数据",
    draggable: true,
    attrs: {
      text: {
        fill: "#fff",
        fontSize: 12,
      },
      body: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        fill: "transparent",
        rx: 0,
        ry: 0,
      },
    },
  });
  const target2 = graph.addNode({
    x: 110,
    y: 350,
    width: 60,
    height: 20,
    label: "模拟数据",
    attrs: {
      text: {
        fill: "#fff",
        fontSize: 12,
      },
      body: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        fill: "transparent",
        rx: 0,
        ry: 0,
      },
    },
  });
  // 连接两个节点
  graph.addEdge({
    source: { x: 60, y: 300 },
    target: target1,
    attrs: {
      line: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
  });
  graph.addEdge({
    source: { x: 140, y: 300 },
    target: target2,
    attrs: {
      line: {
        stroke: "rgb(255,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
  });
  // 右侧支线1
  graph.addEdge({
    source: { x: 230, y: 225 },
    target: { x: 500, y: 490 },
    id: "edge-1",
    vertices: [
      { x: 500, y: 225 },
      { x: 500, y: 380 },
      { x: 20, y: 380 },
      { x: 20, y: 490 },
    ],
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 70,
          x: 0,
          y: -30,
        },
      },
    },
    labels: [
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: 17,
            refY: -170,
            refWidth: 35,
            refHeight: 35,
            stroke: "rgb(0,255,0)",
            fill: "transparent",
            strokeWidth: 1,
            rx: 50,
            ry: 500,
          },
        },
        position: 0.5,
      },
      {
        markup: [
          {
            tagName: "rect",
            selector: "labelBody",
          },
        ],
        attrs: {
          labelBody: {
            ref: "",
            refX: 302,
            refY: -90,
            refWidth: 10,
            refHeight: 30,
            stroke: "rgb(0,255,0)",
            fill: "rgb(0,255,0)",
            strokeWidth: 1,
            rx: 0,
            ry: 0,
          },
        },
        position: 0.49,
      },
      {
        data: { name: "模拟数据" },
        position: 0,
      },
      {
        data: { name: "模拟数据", U: "模拟数据", Fz: "0%" },
        position: 0.2,
        attrs: {
          fo: {
            x: -80, // 设置x偏移
            y: 5, // 设置y偏移
          },
        },
      },
    ],
  });
  // 右侧支线下连
  graph.addEdge({
    source: { x: 45, y: 380 },
    target: { x: 45, y: 480 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  graph.addEdge({
    source: { x: 135, y: 380 },
    target: { x: 135, y: 480 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  graph.addEdge({
    source: { x: 225, y: 380 },
    target: { x: 225, y: 480 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  graph.addEdge({
    source: { x: 315, y: 380 },
    target: { x: 315, y: 480 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  graph.addEdge({
    source: { x: 405, y: 380 },
    target: { x: 405, y: 480 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  graph.addEdge({
    source: { x: 45, y: 490 },
    target: { x: 45, y: 590 },
    attrs: {
      line: {
        stroke: "rgb(0,255,0)",
        strokeWidth: 1,
        sourceMarker: "",
        targetMarker: "block",
      },
    },
    defaultLabel: {
      markup: Markup.getForeignObjectMarkup(),
      attrs: {
        fo: {
          width: 80,
          height: 90,
          x: 0,
          y: 0,
        },
      },
    },
    labels: [
      {
        data: {
          name: "模拟数据",
          P: "模拟数据",
          Q: "模拟数据",
          Pg: "模拟数据",
          Qg: "模拟数据",
          Fz: "0%",
        },
        position: 0,
      },
    ],
  });
  // 动态线条
  graph.addEdge({
    id: 'lineDh',
    source: { x: 600, y: 223 },
    target: { x: 600, y: 588 },
    attrs: {
      line: {
        stroke: "rgb(255,0,0)",
        strokeWidth: 1,
        sourceMarker: "",
        strokeDasharray: 10, // 设置虚线模式
        style: {
          animation: "ant-line 30s infinite linear",
        }, // 流动效果
      },
    },
  });
  // 为右侧一绑定箭头动画
  const edge = graph.getCellById("edge-1");
  let markup = edge.getMarkup();
  markup = [markup[0], markup[1]];
  markup.push({
    tagName: "image",
    selector: "circle",
  });
  edge.setMarkup(markup);
  let attrOption = {
    circle: {
      r: 10,
      fill: "rgb(0,255,0)",
      atConnectionRatio: 0,
      width: 18,
      height: 18,
      "xlink:href": imgl,
      x: -3,
      y: -9,
    },
  };
  let options = {
    delay: 0,
    duration: 10000,
    timing: Timing.linear,
    complete: () => {
      edge.setAttrs(attrOption);
      edge.transition("attrs/circle/atConnectionRatio", 1, options);
    },
  };
  edge.setAttrs(attrOption);
  edge.transition("attrs/circle/atConnectionRatio", 1, options);
  const line1 = graph.getCellById('lineDh')
  console.log(line1, 4444);
};

onMounted(() => {
  init();
});
</script>

<style scoped lang="scss">
@import url("@/style/animations.css");

.tuopu {
  h2 {
    text-align: center;
  }
  #container {
    position: relative;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    width: 100%;
    height: 80vh;
  }

  .tooltiptext {
    width: 120px;
    background-color: #fff;
    color: #000;
    text-align: center;
    border-radius: 6px;
    padding: 5px 0;
    position: absolute;
    z-index: 1;
    display: none;
    opacity: 0.9;
    font-weight: 700;
  }
}
</style>
